package org.sloth.core.load
{
	import flash.events.Event;
	
	import org.sloth.core.load.proxy.ILoadProxy;
	import org.sloth.core.load.proxy.LoadProxyFactory;

	/**
	 * 资源加载管理器，默认支持 <code>LoadType</code> 所定义的资源类型。如果未找到指定加载代理，则使用二进制加载代理加载资源
	 */	
	public class LoadMgr
	{
//============================================================================
//CONSTANT
//============================================================================
		private static const _loadProxyFactory:LoadProxyFactory = new LoadProxyFactory();
		private static const _uidProxyMap:Object = {};
		
		private static var _isLoading:Boolean = false;
		private static const _list:Array = [];
//============================================================================
//PUBLIC
//============================================================================
		/**
		 * 立即加载资源
		 * @param url 资源url
		 * @param type 资源类型，由<code>LoadType</code>定义
		 * @param completeCB 资源加载完成后回调函数
		 * @param progressCB 资源加载进度回调函数
		 * @param errorCB 资源加载出错回调函数
		 * @param data 加载资源需要传递的数据
		 * 
		 */		
		public static function add(
			url:String, 
			type:String, 
			completeCB:Function = null, 
			progressCB:Function = null, 
			errorCB:Function = null, 
			data:* = null):void
		{
			var vo:LoadVO = new LoadVO(url, type, completeCB, progressCB, errorCB, data);
			loadVO(vo);
		}
		/**
		 * 将资源添加到等待列表，按列表顺序加载资源
		 * @param url 资源url
		 * @param type 资源类型，由<code>LoadType</code>定义
		 * @param completeCB 资源加载完成后回调函数
		 * @param progressCB 资源加载进度回调函数
		 * @param errorCB 资源加载出错回调函数
		 * @param data 加载资源需要传递的数据
		 * 
		 */		
		public static function append(
			url:String, 
			type:String, 
			completeCB:Function = null, 
			progressCB:Function = null, 
			errorCB:Function = null, 
			data:* = null):void
		{
			var vo:LoadVO = new LoadVO(url, type, completeCB, progressCB, errorCB, data);
			_list.push(vo);
			if (_isLoading) return;
			_isLoading = true;
			load();
		}
		/**
		 * 增加一种资源加载类型代理
		 * @param type 资源类型
		 * @param cls 类型相关代理类ILoadProxy
		 * 
		 */		
		public static function addType(type:String, cls:Class):void
		{
			_loadProxyFactory.addType(type, cls);
		}
//============================================================================
//PRIVATE
//============================================================================
		private static function load():void
		{
			if (_list.length == 0)
			{
				_isLoading = false;
				return;
			}
			var vo:LoadVO = _list.shift();
			loadVO(new LoadVO(vo.url, vo.type, complete_cb, progress_cb, error_cb, vo));
		}
		//====================================================================
		private static function loadVO(vo:LoadVO):void
		{
			var proxy:ILoadProxy = _loadProxyFactory.getProxy(vo.type);
			proxy.addEventListener("error", error_handler);
			proxy.addEventListener("complete", complete_handler);
			proxy.addEventListener("progress", progress_handler);
			
			_uidProxyMap[vo.uid] = proxy;
			
			proxy.load(vo);
		}
//============================================================================
//HANDLER
//============================================================================
		private static function complete_handler(event:Event):void
		{
			var proxy:ILoadProxy = event.currentTarget as ILoadProxy;
			proxy.removeEventListener("complete", complete_handler);
			proxy.removeEventListener("progress", progress_handler);
			proxy.removeEventListener("error", error_handler);
			
			var vo:LoadVO = proxy.vo;
			delete _uidProxyMap[vo.uid];
			
			vo.content = proxy.data;
			if (vo.completeCB != null) vo.completeCB(vo);
		}
		private static function progress_handler(event:Event):void
		{
			var proxy:ILoadProxy = event.currentTarget as ILoadProxy;
			var vo:LoadVO = proxy.vo;
			
			vo.content = proxy.data;
			if (vo.progressCB != null) vo.progressCB(vo);
		}
		private static function error_handler(event:Event):void
		{
			var proxy:ILoadProxy = event.currentTarget as ILoadProxy;
			proxy.removeEventListener("complete", complete_handler);
			proxy.removeEventListener("progress", progress_handler);
			proxy.removeEventListener("error", error_handler);
			
			var vo:LoadVO = proxy.vo;
			delete _uidProxyMap[vo.uid];
			
			vo.content = proxy.data;
			if (vo.errorCB != null) vo.errorCB(vo);
		}
//============================================================================
//CALLBACK
//============================================================================
		private static function complete_cb(vo:LoadVO):void
		{
			var voLoad:LoadVO = vo.data as LoadVO;
			voLoad.content = vo.content;
			if (voLoad.completeCB != null) voLoad.completeCB(voLoad);
			load();
		}
		private static function progress_cb(vo:LoadVO):void
		{
			var voLoad:LoadVO = vo.data as LoadVO;
			voLoad.content = vo.content;
			if (voLoad.progressCB != null) voLoad.progressCB(voLoad);
		}
		private static function error_cb(vo:LoadVO):void
		{
			var voLoad:LoadVO = vo.data as LoadVO;
			voLoad.content = vo.content;
			if (voLoad.errorCB != null) voLoad.errorCB(voLoad);
			load();
		}
	}
}